var waterEffectVertexShaderStr = "\
attribute vec3 inPosition;\
uniform mat4 modelMat;\
uniform mat4 viewProjectionMat;\
varying vec4 outWorldPos;\
void main(void)\
{\
  outWorldPos = modelMat*vec4(inPosition,1.0);\
  gl_Position = viewProjectionMat*outWorldPos;\
}\
";
var waterEffectFragmentShaderStr = "\
uniform sampler2D normapMap;\
uniform sampler2D reflectionMap;\
uniform vec4 waterColor;\
uniform vec4 waterParam0;\
uniform vec3 viewPosition;\
varying vec4 outWorldPos;\
varying vec3 outViewVector;\
void main(void)\
{\
  vec2 uv = (outWorldPos.xz- waterParam0.xy )/waterParam0.z;\
  vec3 n = normalize(( ((texture2D(normapMap,uv)+texture2D(normapMap,uv*3.8))*0.5 ).rbg - 0.5)*2.0);\
  vec3 eye = normalize(viewPosition-outWorldPos.xyz);\
  vec3 r = normalize(reflect(-eye,n));\
  vec3 absR = abs(r);\
  vec2 reflectionCoord;\
  vec3 cubeCoord;\
  if (absR.x > absR.y && absR.x > absR.z){\
    if (r.x>0.0){\
      cubeCoord = vec3(-r.z,-r.y,absR.x);\
      reflectionCoord = 0.25*( cubeCoord.xy/cubeCoord.z +1.0);\
      reflectionCoord = vec2( 1.25-reflectionCoord.t,0.75-reflectionCoord.s);\
    }else{\
      cubeCoord = vec3(r.z,-r.y,absR.x);\
      reflectionCoord = 0.25*( cubeCoord.xy/cubeCoord.z +1.0);\
      reflectionCoord = vec2( -0.25+reflectionCoord.t,0.25+reflectionCoord.s);\
    }\
  } else\
  if (absR.y > absR.x && absR.y > absR.z){\
    cubeCoord = vec3(r.x,r.z,absR.y);\
    reflectionCoord = vec2(0.25,0.25)+0.25*( cubeCoord.xy/cubeCoord.z +1.0 );\
  }\
  else{\
    if (r.z>0.0){\
      cubeCoord = vec3(r.x,-r.y,absR.z);\
      reflectionCoord = 0.25*( cubeCoord.xy/cubeCoord.z +1.0);\
      reflectionCoord = vec2( 0.25+reflectionCoord.s,1.25-reflectionCoord.t);\
    }else{\
      cubeCoord = vec3(-r.x,-r.y,absR.z);\
      reflectionCoord = 0.25*( cubeCoord.xy/cubeCoord.z +1.0);\
      reflectionCoord = vec2( 0.75-reflectionCoord.s,-0.25+reflectionCoord.t);\
    }\
  }\
  vec4 reflectionColor = texture2D(reflectionMap,vec2(reflectionCoord.s,1.0-reflectionCoord.t) );\
  float fresnelTerm = dot(eye, vec3(0.0,1.0,0.0));\
  gl_FragColor = vec4(mix(reflectionColor.rgb,waterColor.rgb,waterColor.a), clamp(1.0-fresnelTerm,0.0,1.0));\
}\
";
function gewWaterEffect(game)
{
  // General properties
  this.game = game;
  this.gl = game.gl;
  var gl = game.gl;
  this.name = "WaterEffect";
  this.scene3d = null;//Current scene3d that using this effect 
  this.materialList = {};
  this.currentPass = null;
  
  // Shader properties
  this.vs = createVertexShader(gl,waterEffectVertexShaderStr);
  this.fs = createFragmentShader(gl,waterEffectFragmentShaderStr);
  var program = gl.createProgram();
  gl.attachShader(program,this.vs);
  gl.attachShader(program,this.fs);
  gl.linkProgram(program);
  checkProgramLinkStatus(gl,program);
  this.program = program;
  // Shader param id
  this.inPosition = gl.getAttribLocation(program,"inPosition");
  this.viewProjectionMat = gl.getUniformLocation(program, "viewProjectionMat");
  this.viewPosition = gl.getUniformLocation(program, "viewPosition");
  this.normapMap = gl.getUniformLocation(program, "normapMap");
  this.reflectionMap = gl.getUniformLocation(program, "reflectionMap");
  this.modelMat = gl.getUniformLocation(program, "modelMat");
  //this.lightVector= gl.getUniformLocation(program, "lightVector");
  //this.lightColor= gl.getUniformLocation(program, "lightColor");
  this.waterColor= gl.getUniformLocation(program, "waterColor");
  this.waterParam0= gl.getUniformLocation(program, "waterParam0");
}
gewWaterEffect.prototype.destructor = function()
{
  var list  = this.materialList;
  var listLen = list.length;  
  for (var i in list)
  {
    list[i].destructor();
  }
  this.scene3d.removeEffect(this);
},
gewWaterEffect.prototype.render = function(scene3d) 
{
  var gl = this.gl; 
  var game = this.game;
  this.scene3d = scene3d;
  // push GL state
  // set GL state
  gl.useProgram(this.program);
  gl.enableVertexAttribArray(this.inPosition);
  gl.enable(gl.DEPTH_TEST);
  gl.enable(gl.BLEND);
  gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
  //gl.enable(gl.CULL_FACE);
  this.currentPass = 0;
  var materialList = this.materialList;
  var listLen = materialList.length;
  var viewPos = scene3d.viewPosition;
  gl.uniform3f(this.viewPosition, viewPos.x, viewPos.y, viewPos.z);
  var viewProj = scene3d.viewProjectMat;
  gl.uniformMatrix4fv(this.viewProjectionMat, false, viewProj.data);
  //var mainLightData = scene3d.mainLight.lightData;
  //gl.uniform3f(this.lightVector, mainLightData[0], mainLightData[1], mainLightData[2]);
  //gl.uniform3f(this.lightColor, mainLightData[6], mainLightData[7], mainLightData[8]);
  for(var i in materialList)
  { 
    materialList[i].render();
  }
  //
  gl.currentPass = null;
  // pop GL state  
  gl.disable(gl.DEPTH_TEST);
  gl.disable(gl.BLEND);
  //gl.disable(gl.CULL_FACE);
  gl.disableVertexAttribArray(this.inPosition);
  //gl.disableVertexAttribArray(this.inNormal);
  //gl.disableVertexAttribArray(this.inTexCoord0);
}
